package com.scheduling.machine.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.scheduling.common.exception.BusinessException;
import com.scheduling.machine.entity.MachineTypeMaterialCompatibility;
import com.scheduling.machine.mapper.MachineTypeMaterialCompatibilityMapper;
import com.scheduling.machine.service.IMachineTypeMaterialCompatibilityService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 机器类型原料兼容性服务实现类
 *
 * @author 开发团队
 * @since 2025-05-29
 */
@Slf4j
@Service
public class MachineTypeMaterialCompatibilityServiceImpl
        extends ServiceImpl<MachineTypeMaterialCompatibilityMapper, MachineTypeMaterialCompatibility>
        implements IMachineTypeMaterialCompatibilityService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MachineTypeMaterialCompatibility createCompatibility(MachineTypeMaterialCompatibility compatibility) {
        if (compatibility == null) {
            throw new BusinessException("兼容性配置不能为空");
        }

        if (!StringUtils.hasText(compatibility.getMachineTypeId()) || !StringUtils.hasText(compatibility.getMaterialId())) {
            throw new BusinessException("机器类型ID和原料ID不能为空");
        }

        // 检查是否已存在相同配置
        MachineTypeMaterialCompatibility existing = baseMapper.selectByMachineTypeAndMaterial(
                compatibility.getMachineTypeId(), compatibility.getMaterialId());
        if (existing != null) {
            throw new BusinessException("该机器类型与原料的兼容性配置已存在");
        }

        boolean saved = this.save(compatibility);
        if (!saved) {
            throw new BusinessException("兼容性配置保存失败");
        }

        log.info("创建兼容性配置成功: {}", compatibility.getCompatibilityId());
        return compatibility;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MachineTypeMaterialCompatibility updateCompatibility(MachineTypeMaterialCompatibility compatibility) {
        if (compatibility == null || !StringUtils.hasText(compatibility.getCompatibilityId())) {
            throw new BusinessException("兼容性配置ID不能为空");
        }

        MachineTypeMaterialCompatibility existing = this.getById(compatibility.getCompatibilityId());
        if (existing == null) {
            throw new BusinessException("兼容性配置不存在: " + compatibility.getCompatibilityId());
        }

        boolean updated = this.updateById(compatibility);
        if (!updated) {
            throw new BusinessException("兼容性配置更新失败");
        }

        log.info("更新兼容性配置成功: {}", compatibility.getCompatibilityId());
        return this.getById(compatibility.getCompatibilityId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteCompatibility(String compatibilityId) {
        if (!StringUtils.hasText(compatibilityId)) {
            throw new BusinessException("兼容性配置ID不能为空");
        }

        boolean deleted = this.removeById(compatibilityId);
        if (deleted) {
            log.info("删除兼容性配置成功: {}", compatibilityId);
        }

        return deleted;
    }

    @Override
    public MachineTypeMaterialCompatibility getCompatibilityDetail(String compatibilityId) {
        if (!StringUtils.hasText(compatibilityId)) {
            throw new BusinessException("兼容性配置ID不能为空");
        }

        MachineTypeMaterialCompatibility result = this.getById(compatibilityId);
        if (result == null) {
            throw new BusinessException("兼容性配置不存在: " + compatibilityId);
        }

        return result;
    }

    @Override
    public Page<MachineTypeMaterialCompatibility> getCompatibilityPage(long current, long size,
                                                                       String machineTypeId, String materialId,
                                                                       Boolean compatible) {
        Page<MachineTypeMaterialCompatibility> page = new Page<>(current, size);
        LambdaQueryWrapper<MachineTypeMaterialCompatibility> queryWrapper = new LambdaQueryWrapper<>();

        if (StringUtils.hasText(machineTypeId)) {
            queryWrapper.eq(MachineTypeMaterialCompatibility::getMachineTypeId, machineTypeId);
        }
        if (StringUtils.hasText(materialId)) {
            queryWrapper.eq(MachineTypeMaterialCompatibility::getMaterialId, materialId);
        }
        if (compatible != null) {
            queryWrapper.eq(MachineTypeMaterialCompatibility::getCompatible, compatible);
        }

        queryWrapper.orderByDesc(MachineTypeMaterialCompatibility::getUpdateTime);

        return this.page(page, queryWrapper);
    }

    @Override
    public boolean isCompatible(String machineTypeId, String materialId) {
        if (!StringUtils.hasText(machineTypeId) || !StringUtils.hasText(materialId)) {
            log.warn("机器类型ID或原料ID为空，默认不兼容");
            return false;
        }

        MachineTypeMaterialCompatibility compatibility = baseMapper.selectByMachineTypeAndMaterial(machineTypeId,
                materialId);

        // 如果没有配置记录，默认不兼容（保守策略）
        if (compatibility == null) {
            log.warn("未找到机器类型[{}]与原料[{}]的兼容性配置，默认不兼容", machineTypeId, materialId);
            return false;
        }

        return compatibility.getCompatible();
    }

    @Override
    public MachineTypeMaterialCompatibility getCompatibilityDetail(String machineTypeId, String materialId) {
        if (!StringUtils.hasText(machineTypeId) || !StringUtils.hasText(materialId)) {
            throw new BusinessException("机器类型ID和原料ID不能为空");
        }

        return baseMapper.selectByMachineTypeAndMaterial(machineTypeId, materialId);
    }

    @Override
    @Transactional(readOnly = true)
    public void validateMaterialsCompatibility(String machineTypeId, List<String> materialIds) {
        if (!StringUtils.hasText(machineTypeId)) {
            throw new BusinessException("机器类型ID不能为空");
        }

        if (CollectionUtils.isEmpty(materialIds)) {
            return; // 没有原料需求，无需验证
        }

        List<MachineTypeMaterialCompatibility> compatibilityList =
                baseMapper.checkMaterialsCompatibility(machineTypeId, materialIds);

        // 检查是否有不兼容的原料
        List<MachineTypeMaterialCompatibility> incompatibleMaterials = compatibilityList.stream()
                .filter(c -> !c.getCompatible())
                .collect(Collectors.toList());

        if (!incompatibleMaterials.isEmpty()) {
            StringBuilder errorMsg = new StringBuilder("以下原料与机器类型不兼容：");
            for (MachineTypeMaterialCompatibility incompatible : incompatibleMaterials) {
                errorMsg.append("\n- 原料ID: ").append(incompatible.getMaterialId());
                if (StringUtils.hasText(incompatible.getReason())) {
                    errorMsg.append("，原因: ").append(incompatible.getReason());
                }
            }
            throw new BusinessException(errorMsg.toString());
        }

        // 检查是否有未配置的原料
        List<String> configuredMaterialIds = compatibilityList.stream()
                .map(MachineTypeMaterialCompatibility::getMaterialId)
                .collect(Collectors.toList());

        List<String> unconfiguredMaterials = materialIds.stream()
                .filter(materialId -> !configuredMaterialIds.contains(materialId))
                .collect(Collectors.toList());

        if (!unconfiguredMaterials.isEmpty()) {
            String errorMsg = "以下原料未配置兼容性，默认不兼容: " + String.join(", ", unconfiguredMaterials);
            throw new BusinessException(errorMsg);
        }
    }

    @Override
    public List<MachineTypeMaterialCompatibility> getCompatibleMaterials(String machineTypeId) {
        if (!StringUtils.hasText(machineTypeId)) {
            throw new BusinessException("机器类型ID不能为空");
        }

        return baseMapper.selectCompatibleMaterials(machineTypeId);
    }

    @Override
    public List<MachineTypeMaterialCompatibility> getCompatibleMachineTypes(String materialId) {
        if (!StringUtils.hasText(materialId)) {
            throw new BusinessException("原料ID不能为空");
        }

        LambdaQueryWrapper<MachineTypeMaterialCompatibility> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MachineTypeMaterialCompatibility::getMaterialId, materialId)
                .eq(MachineTypeMaterialCompatibility::getCompatible, true)
                .orderByDesc(MachineTypeMaterialCompatibility::getUpdateTime);

        return this.list(queryWrapper);
    }

    @Override
    public List<MachineTypeMaterialCompatibility> getIncompatibleMaterials(String machineTypeId) {
        if (!StringUtils.hasText(machineTypeId)) {
            throw new BusinessException("机器类型ID不能为空");
        }

        return baseMapper.selectIncompatibleMaterials(machineTypeId);
    }

    @Override
    public List<MachineTypeMaterialCompatibility> checkBatchCompatibility(String machineTypeId,
                                                                          List<String> materialIds) {
        if (!StringUtils.hasText(machineTypeId)) {
            throw new BusinessException("机器类型ID不能为空");
        }

        if (CollectionUtils.isEmpty(materialIds)) {
            return List.of();
        }

        return baseMapper.checkMaterialsCompatibility(machineTypeId, materialIds);
    }

    @Override
    @Transactional
    public void setCompatibility(String machineTypeId, String materialId, Boolean compatible, String reason) {
        if (!StringUtils.hasText(machineTypeId) || !StringUtils.hasText(materialId)) {
            throw new BusinessException("机器类型ID和原料ID不能为空");
        }

        if (compatible == null) {
            throw new BusinessException("兼容性状态不能为空");
        }

        // 查询是否已存在配置
        MachineTypeMaterialCompatibility existing = baseMapper.selectByMachineTypeAndMaterial(machineTypeId,
                materialId);

        if (existing != null) {
            // 更新现有配置
            existing.setCompatible(compatible);
            existing.setReason(reason);
            existing.setUpdateTime(LocalDateTime.now());
            updateById(existing);
            log.info("更新机器类型[{}]与原料[{}]的兼容性配置: {}", machineTypeId, materialId, compatible);
        } else {
            // 创建新配置
            MachineTypeMaterialCompatibility newCompatibility = new MachineTypeMaterialCompatibility();
            newCompatibility.setMachineTypeId(machineTypeId);
            newCompatibility.setMaterialId(materialId);
            newCompatibility.setCompatible(compatible);
            newCompatibility.setReason(reason);
            save(newCompatibility);
            log.info("创建机器类型[{}]与原料[{}]的兼容性配置: {}", machineTypeId, materialId, compatible);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<MachineTypeMaterialCompatibility> batchCreateCompatibility(List<MachineTypeMaterialCompatibility> compatibilities) {
        if (CollectionUtils.isEmpty(compatibilities)) {
            throw new BusinessException("兼容性配置列表不能为空");
        }

        List<MachineTypeMaterialCompatibility> result = new ArrayList<>();

        for (MachineTypeMaterialCompatibility compatibility : compatibilities) {
            if (!StringUtils.hasText(compatibility.getMachineTypeId()) || !StringUtils.hasText(compatibility.getMaterialId())) {
                throw new BusinessException("机器类型ID和原料ID不能为空");
            }

            // 检查是否已存在相同配置
            MachineTypeMaterialCompatibility existing = baseMapper.selectByMachineTypeAndMaterial(
                    compatibility.getMachineTypeId(), compatibility.getMaterialId());
            if (existing != null) {
                log.warn("兼容性配置已存在，跳过: 机器类型[{}] - 原料[{}]",
                        compatibility.getMachineTypeId(), compatibility.getMaterialId());
                continue;
            }

            boolean saved = this.save(compatibility);
            if (saved) {
                result.add(compatibility);
            }
        }

        log.info("批量创建兼容性配置完成，成功创建{}条记录", result.size());
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchUpdateCompatibility(List<String> compatibilityIds, Boolean compatible, String reason) {
        if (CollectionUtils.isEmpty(compatibilityIds)) {
            return 0;
        }

        if (compatible == null) {
            throw new BusinessException("兼容性状态不能为空");
        }

        LambdaUpdateWrapper<MachineTypeMaterialCompatibility> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(MachineTypeMaterialCompatibility::getCompatibilityId, compatibilityIds)
                .set(MachineTypeMaterialCompatibility::getCompatible, compatible)
                .set(MachineTypeMaterialCompatibility::getReason, reason)
                .set(MachineTypeMaterialCompatibility::getUpdateTime, LocalDateTime.now());

        boolean updated = this.update(updateWrapper);
        int updatedCount = updated ? compatibilityIds.size() : 0;

        log.info("批量更新兼容性配置完成，影响{}条记录", updatedCount);
        return updatedCount;
    }
} 